import type { ElTree, LoadFunction } from "element-plus";
import type { DeptDetailResult } from "@/api/types";
import { useDebounceFn } from "@vueuse/core";
import { computed, defineComponent, onMounted, ref, watch } from "vue";
import { deptApi } from "@/api";
import IconifyIcon from "@/components/ReIcon/src/iconifyIcon";
import { userDeptStorage } from "@/config/storage";
import { $t } from "@/plugins/i18n";
import { useUserDeptStore } from "@/stores/userDept";

interface Props {
    /** 是否启用懒加载, 如果部门数据量较大则建议开启 */
    lazy?: boolean;
    /** 懒加载模式下向下加载一层并展开 */
    expandInit?: boolean;
    /** 最大加载层数, 从 1 开始, -1 表示不限制 */
    maxLevel?: number;
    /** 可以被选中的层级, 空数组表示全部可选 */
    selectedLevel?: number[];
}

/** DeptTree 组件暴露的属性和方法 */
export interface DeptTreeExpose {
    /** 树组件引用 */
    innerTreeRef: InstanceType<typeof ElTree> | null;
}

export default defineComponent((props: Props, { attrs, emit, expose }) => {
    const { lazy } = props;
    const expandInit = computed(() => props.maxLevel === 1 ? false : !!props.expandInit);
    const maxLevel = computed(() => props.maxLevel ?? -1);
    const selectedLevel = computed(() => props.selectedLevel ?? []);

    /** 当前用户的部门 */
    const userDeptId = useUserDeptStore().id;
    const userDeptCode = useUserDeptStore().code;

    /** 记录已经展开过的节点, 用于 searchLoadCount 计算 */
    const expandedKeys = ref<string[]>([]);

    /** 默认展开当前用户的部门节点 */
    if (expandInit.value) {
        expandedKeys.value.push(userDeptCode);
    }

    /** 当前默认展开的节点 */
    const defaultExpandedKeys = computed(() => {
        const defaultKeys = expandInit.value ? [userDeptCode] : [];
        // bugfix 替换 expandedKeys, 解决当手动折叠部分节点时, 点击其他节点时会展开 expandedKeys 的节点的 bug
        return searchLoadCount.value <= 0 ? defaultKeys : expandedKeys.value;
    });

    // #region ================= 加载全部数据 =================

    const treeData = ref<any>([]);
    const getData = (): void => {
        if (lazy) return;
        deptApi.listTree(userDeptCode).then((resp) => {
            if (ok(resp)) {
                treeData.value = resp.data;
            }
        });
    };

    onMounted(() => {
        getData();
        emit("nodeClick", userDeptStorage.value!);
    });

    // #endregion ================= 加载全部数据 ==============
    // #region ==================== 懒加载 ===================

    const loadNode: LoadFunction = (node, resolve, reject) => {
        if (node.level === 0) {
            deptApi.findById(userDeptId).then((resp) => {
                if (ok(resp)) {
                    // 限制最大层数
                    if (maxLevel.value >= 0 && resp.data.level >= maxLevel.value) {
                        resp.data.isLeaf = true;
                    }
                    // 设置不可选中的层级
                    if (selectedLevel.value.length !== 0 && selectedLevel.value.includes(resp.data.level)) {
                        resp.data.disabled = true;
                    }
                    resolve([resp.data]);
                }
            });
        } else {
            if (searchLoadCount.value === 0) {
                reject(); // 当搜索结束时, 不再加载下面节点, 保持搜索一致性
                return;
            };
            const startTime = Date.now();
            deptApi.listChildren(node.data.id).then((resp) => {
                if (ok(resp)) {
                    const endTime = Date.now();
                    const delay = endTime - startTime < 300 ? 300 - (endTime - startTime) : 0;
                    // 模拟网络延迟, 保持动画效果
                    setTimeout(() => {
                        // 搜索时加载计数减一
                        if (searchLoadCount.value > 0) {
                            searchLoadCount.value--;
                        }
                        // 限制最大层数
                        if (maxLevel.value >= 0 && resp.data.length && resp.data[0].level >= maxLevel.value) {
                            resp.data.forEach((dept) => {
                                dept.isLeaf = true;
                            });
                        }
                        // 设置不可选中的层级
                        if (selectedLevel.value.length !== 0) {
                            resp.data.forEach((dept) => {
                                if (selectedLevel.value.includes(dept.level)) {
                                    (dept).disabled = true;
                                }
                            });
                        }
                        resolve(resp.data);
                    }, delay);
                } else {
                    reject();
                }
            });
        }
    };

    // #endregion ================= 懒加载 ===================
    // #region ==================== 搜索 =====================

    /** 树组件引用 */
    const treeRef = ref<InstanceType<typeof ElTree> | null>(null);
    /** 过滤文本 */
    const filterText = ref("");
    /** 过滤节点代码列表 */
    const filterCodes = ref<string[]>([]);
    /** 搜索加载计数, -1 表示不用请求接口, 0 表示请求接口搜索完成, > 0 表示正在请求接口 */
    const searchLoadCount = ref(-1);

    /** 过滤节点 */
    const filterNode = (value: string, data: DeptDetailResult): boolean => {
        return data.name.includes(value);
    };

    // 防抖处理过滤逻辑
    const debouncedFilter = useDebounceFn(async (text: string) => {
        filterCodes.value = [];
        if (lazy) {
            await searchDeptByName(text); // 等待 searchLoadCount 更新完成
            if (!text || searchLoadCount.value <= 0) {
                treeRef.value?.filter(text);
            }
        } else {
            treeRef.value?.filter(text);
        }
    }, 300);

    const treeNodeExpand = (data: DeptDetailResult): void => {
        // 去重添加展开项
        expandedKeys.value = [...new Set(expandedKeys.value).add(data.code)];
    };

    /** 根据名称搜索部门 */
    const searchDeptByName = async (name: string): Promise<void> => {
        searchLoadCount.value = -1;
        if (!name.trim()) {
            return;
        }
        const payload = {
            name,
            code: userDeptCode,
            maxLevel: maxLevel.value,
        };
        const resp = await deptApi.listByName(payload);
        if (ok(resp)) {
            const codes = resp.data.map(dept => dept.code.split(".").slice(0, -1));
            const set = new Set<string>();
            codes.forEach((codeParts) => {
                let code = "";
                codeParts.forEach((part) => {
                    code += (code ? "." : "") + part;
                    set.add(code);
                });
            });
            const setArray = Array.from(set);
            // 计算需要加载的节点数量
            searchLoadCount.value = setArray.filter(code => !expandedKeys.value.includes(code)).length || -1;
            // 去重后添加展开项
            expandedKeys.value = [...new Set([...expandedKeys.value, ...setArray])];
        }
    };

    // 监听过滤文本变化，触发树组件过滤
    watch(filterText, (val) => {
        const text = (val || "").trim();
        if (text !== filterText.value) filterText.value = text;
        debouncedFilter(text);
    });

    // 监听搜索加载计数变化，当全部加载完成后触发树组件过滤
    watch(searchLoadCount, (val) => {
        if (val <= 0) {
            treeRef.value?.filter(filterText.value);
        }
    });

    // #endregion ================= 搜索 =====================

    const treeNodeClick = (data: DeptDetailResult): void => {
        if (data.disabled) return;
        emit("nodeClick", data);
    };

    expose<DeptTreeExpose>({
        /** 树组件引用 */
        get innerTreeRef() {
            return treeRef.value;
        },
    });

    return () => (
        <div>
            <el-input
                v-model={filterText.value}
                class="mb-2"
                placeholder={$t("placeholder.searchOrg")}
                clearable
            />
            <el-tree
                ref={treeRef}
                {...attrs}
                data={treeData.value}
                expand-on-click-node={false}
                node-key="code"
                props={{
                    label: "name",
                    children: "children",
                    isLeaf: "isLeaf",
                    disabled: "disabled",
                }}
                load={loadNode}
                lazy={lazy}
                filter-node-method={filterNode}
                default-expanded-keys={defaultExpandedKeys.value}
                onNodeExpand={treeNodeExpand}
                onNodeClick={treeNodeClick}
            >
                {{
                    default: ({ data }: { data: DeptDetailResult }) => (
                        <div class="flex items-center gap-1">
                            {
                                data.icon && <IconifyIcon icon={data.icon} />
                            }
                            <span class={data.disabled ? "text-(--el-disabled-text-color) cursor-not-allowed" : ""}>
                                {data.name}
                            </span>
                        </div>
                    ),
                }}
            </el-tree>
        </div>
    );
}, {
    name: "DeptTree",
    props: {
        lazy: {
            type: Boolean,
            default: true,
        },
        expandInit: {
            type: Boolean,
            default: true,
        },
        maxLevel: {
            type: Number,
            default: -1,
        },
        selectedLevel: {
            type: Array,
            default: () => [],
        },
    },
    emits: {
        /** 点击节点时触发 */
        nodeClick: (data: DeptDetailResult) => data instanceof Object,
    },
});
